package com.jboltai.event.chain;

import cn.hutool.core.util.ArrayUtil;
import com.jboltai.capability.message.AIIntention;
import com.jboltai.config.JBoltAIConfig;
import com.jboltai.event.EventState;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.HashMap;

public class IntentionChainNode extends ChainNode<IntentionChainNode>{
    private static final Logger LOGGER = LoggerFactory.getLogger(JBoltAIConfig.LOGGER_NAME);

    private IntentionSupplier intentionSupplier;

    private AIIntention intention;


    public IntentionChainNode(IntentionSupplier eventSupplier) {
        this.intentionSupplier = eventSupplier;
    }

    public IntentionChainNode(String id, IntentionSupplier eventSupplier) {
        this.intentionSupplier = eventSupplier;
        this.id = id;
    }

    @Override
    protected void execute() {


        try {
            this.intention = this.intentionSupplier.supply(chain);
            this.success();
        } catch (Exception e) {
            LOGGER.error("IntentionChainNode类型节点执行过程中发生异常", e);
            this.fail(e.getMessage(), e);

        }
    }


    @Override
    public void success() {
        chain.removeFromRunning(this.id);
        setState(EventState.SUCCESS);

        ChainNode[] successNodes = getAfterNodes(AFTER_KEY_SUCCESS);
        ChainNode[] intentionNodes = null;
        if (intention == null || intention == AIIntention.NO_MATCH) {
            intentionNodes = getAfterNodes(AIIntention.NO_MATCH_KEY);
        } else {
            intentionNodes = getAfterNodes(intention.getKey());
        }

        if ((successNodes == null || successNodes.length == 0) && (intentionNodes == null || intentionNodes.length == 0)) {
            //自己就是最后的节点了，通知父节点完事了
            tryComplete();
            return;
        }
        if (successNodes != null && successNodes.length > 0) {
            for (ChainNode after : successNodes) {
                this.chain.startNode(after);
            }
        }
        if (intentionNodes != null && intentionNodes.length > 0) {
            for (ChainNode after : intentionNodes) {
                this.chain.startNode(after);
            }
        }

    }


    /**
     * 尝试完结
     */
    @Override
    protected void tryComplete() {

        if (chain.getState() != EventState.PROCESSING) {
            //chain 已经被改变了，不需要再通知了
            return;
        }

        boolean l = lock.tryLock();
        //锁都获取不到，肯定当前在执行中，那就不可能完结
        if (!l) return;

        try {
            boolean allAfterDone = false;


            ChainNode[] afterNodes = new ChainNode[0];
            if (this.state == EventState.FAIL) {
                afterNodes = getAfterNodes(AFTER_KEY_FAIL);
            } else {
                ChainNode[] successNodes = getAfterNodes(AFTER_KEY_SUCCESS);
                ChainNode[] intentionNodes = null;
                if (intention == null || intention == AIIntention.NO_MATCH) {
                    intentionNodes = getAfterNodes(AIIntention.NO_MATCH_KEY);
                } else {
                    intentionNodes = getAfterNodes(intention.getKey());
                }
                afterNodes = ArrayUtil.addAll(afterNodes, successNodes, intentionNodes);
            }


            if (afterNodes == null || afterNodes.length == 0) {
                allAfterDone = true;
            } else {
                allAfterDone = Arrays.stream(afterNodes).allMatch(item -> (
                        item.state == EventState.SUCCESS ||
                                item.state == EventState.FAIL ||
                                item.state == EventState.CANCEL
                ));
            }

            if (allAfterDone) {
                // 所有后续节点都执行完毕，有父级节点就通知父级节点检查是否可以完结
                if (this.prevs != null && this.prevs.length > 0) {
                    for (ChainNode prev : this.prevs) {
                        prev.tryComplete();
                    }
                } else {
                    chain.tryComplete();
                }
            }
        } finally {
            lock.unlock();
        }



    }


    public IntentionSupplier getIntentionSupplier() {
        return intentionSupplier;
    }



}
